package com.kma.summer2012.facade;

import com.kma.summer2012.dao.*;
import com.kma.summer2012.factory.DAOFactory;
import com.kma.summer2012.factory.SpringBeansFactory;
import com.kma.summer2012.model.*;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;

public class RequestFacadeImpl implements RequestFacade {
    //@Override
    public void changeState(int id, String comment, int senderId) throws Exception {

        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsRequest request = factory.getCrumbsRequestDAO().getById(id);
        int newState;
        //change request state, depending on the state in which it was
        if (request.getCrumbsRequestsState().getId() == 3) //assessed--->need more info
            newState = 4;
        else  //need more info, in pogress --->  rejected
        {
            newState = 5;
            request.setCrumbsUsers(null);
            Set<CrumbsDateAndTime> dates = new HashSet<CrumbsDateAndTime>();
            for (CrumbsDateAndTime date : request.getCrumbsDateAndTimes()) {
                if (date.getAssignedTimeEnd() != null) {
                    date.setAssignedTimeBegin(null);
                    date.setAssignedTimeEnd(null);
                }
                dates.add(date);
            }
            request.setCrumbsDateAndTimes(dates);
        }
        request.setCrumbsRequestsState(factory.getCrumbsRequestsStateDAO().getById(newState));
        factory.getCrumbsRequestDAO().update(request);

        //add comment in CrumbsProcessHistory
        CrumbsProcessHistory cph = new CrumbsProcessHistory();
        cph.setCommentText(comment);
        long time = System.currentTimeMillis();
        cph.setFixedDate(new java.sql.Date(time));
        Set<CrumbsProcessHistory> history = request.getCrumbsProcessHistories();
        ArrayList<CrumbsProcessHistory> historyArrayList = new ArrayList<CrumbsProcessHistory>();
        historyArrayList.addAll(history);
        Collections.sort(historyArrayList, new Comparator<CrumbsProcessHistory>() {
            @Override
            public int compare(CrumbsProcessHistory o1, CrumbsProcessHistory o2) {
                return o1.getId() - o2.getId();
            }
        });
        int i = historyArrayList.size() - 1;
        /*for (;i>0;i--){
            if (historyArrayList.get(i).getCrumbsUserBySenderId().getUserId()!=historyArrayList.get(i).getCrumbsUserByRecieverId().getUserId()){
                break;
            }
        }
        if(i>=0){ */
        // CrumbsProcessHistory lastItem = historyArrayList.get(i);
        //   cph.setCrumbsUserByRecieverId(lastItem.getCrumbsUserBySenderId());
        if (newState == 4) {
            cph.setCrumbsUserByRecieverId(factory.getCrumbsUserDAO().getById(4));
        } else {
            for (; i > 0; i--) {
                if (historyArrayList.get(i).getCrumbsUserBySenderId().getCrumbsPosition().getId() == 1) {
                    break;
                }
            }
            cph.setCrumbsUserByRecieverId(historyArrayList.get(i).getCrumbsUserBySenderId());
        }
        cph.setCrumbsUserBySenderId(factory.getCrumbsUserDAO().getById(senderId));
        cph.setCrumbsRequest(request);
        factory.getCrumbsProcessHistoryDAO().add(cph);

    }

    @Override
    public Boolean assignRequest(int user_id, int request_id, Date assignDateBegin, Date assignDateEnd) throws Exception {
        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsDateAndTimeDAO dao = (CrumbsDateAndTimeDAO) factory.getCrumbsDateAndTimeDAO();
        CrumbsRequest request = factory.getCrumbsRequestDAO().getById(request_id);
        boolean go = true;
        for (CrumbsDateAndTime dates : request.getCrumbsDateAndTimes()) {
            if (assignDateBegin.before(dates.getDateBegin()) || assignDateEnd.after(dates.getDateEnd())) {
                go = false;
            }

        }
        //check if our assigned time in requested time
        if (timeCheck(assignDateBegin, assignDateEnd, user_id, request_id) && go) {

            if (!request.getCrumbsUsers().isEmpty()) {
                request.getCrumbsUsers().clear();
                factory.getCrumbsRequestDAO().update(request);
                for (CrumbsDateAndTime dateTime : dao.getByRequestId(request_id)) {
                    dateTime.setAssignedTimeBegin(null);
                    dateTime.setAssignedTimeEnd(null);
                    factory.getCrumbsDateAndTimeDAO().update(dateTime);
                }
            }


            //assign time
            for (CrumbsDateAndTime dateTime : dao.getByRequestId(request_id)) {
                dateTime.setAssignedTimeBegin(assignDateBegin);
                dateTime.setAssignedTimeEnd(assignDateEnd);
                factory.getCrumbsDateAndTimeDAO().update(dateTime);
            }

            //assign user

            CrumbsRequest crumbsRequest = factory.getCrumbsRequestDAO().getById(request_id);
            CrumbsUser crumbsUser = factory.getCrumbsUserDAO().getById(user_id);

            Set<CrumbsRequest> setRequests = crumbsUser.getCrumbsRequests();
            setRequests.add(crumbsRequest);
            crumbsUser.setCrumbsRequests(setRequests);
            factory.getCrumbsUserDAO().update(crumbsUser);

            return true;
        } else

            return false;


    }


    public Boolean timeCheck(Date assignDateBegin, Date assignDateEnd, int user_id, int request_id) throws Exception {
        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsUser crumbsUser = factory.getCrumbsUserDAO().getById(user_id);
        for (CrumbsRequest request : crumbsUser.getCrumbsRequests()) {
            if (request.getId() != request_id) {
//            if (request.getCrumbsRequestsState().getId() == factory.getCrumbsRequestsStateDAO().getById(2).getId()) {
                //System.out.println(request.getCrumbsRequestsState().getId() + " not " + factory.getCrumbsRequestsStateDAO().getById(2).getId());
                for (CrumbsDateAndTime crumbsDateAndTime : request.getCrumbsDateAndTimes()) {
                    if ((crumbsDateAndTime.getAssignedTimeBegin()) != null) {
                        Date dateBegin = crumbsDateAndTime.getAssignedTimeBegin();
                        Date dateEnd = crumbsDateAndTime.getAssignedTimeEnd();
                        if ((getYear(dateBegin).equals(getYear(assignDateBegin))) && (getMonth(dateBegin).equals(getMonth(assignDateBegin))) && (getDay(dateBegin).equals(getDay(assignDateBegin)))) {
                            int requestHourBegin = getOurTime(dateBegin);
                            int requestHourEnd = getOurTime(dateEnd);
                            int assignTimeBegin = getOurTime(assignDateBegin);
                            int assignTimeEnd = getOurTime(assignDateEnd);
                            if (((assignTimeBegin < requestHourEnd) && (assignTimeEnd > requestHourBegin))) {
                                return false;
                            }
                            //return ((assignTimeBegin >= requestHourEnd) || (assignTimeEnd <= requestHourBegin));

                        }
                    }
                }
            }
        }

        return true;
    }

    Integer getOurTime(Date d) {

        Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance 7
        calendar.setTime(d);   // assigns calendar to given date
        return calendar.get(Calendar.HOUR_OF_DAY); // gets hour in 24h format
    }

    Integer getDay(Date d) {

        Calendar calendar = GregorianCalendar.getInstance();
        calendar.setTime(d);
        return calendar.get(Calendar.DAY_OF_MONTH);
    }

    Integer getMonth(Date d) {

        Calendar calendar = GregorianCalendar.getInstance();
        calendar.setTime(d);
        return calendar.get(Calendar.MONTH);
    }

    Integer getYear(Date d) {

        Calendar calendar = GregorianCalendar.getInstance();
        calendar.setTime(d);
        return calendar.get(Calendar.YEAR);
    }


    //@Override
    public void changeState(int id, int state) throws Exception {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    public boolean sendClientReport(CrumbsClient client, CrumbsRequest request) throws MessagingException {
        Session m_Session;
        Message m_simpleMessage;
        InternetAddress m_fromAddress;
        InternetAddress m_toAddress;
        Properties m_properties;


        m_properties = new Properties();
        //m_properties.put("mail.smtp.host", "smtp.gmail.com");
        // m_properties.put("mail.smtp.socketFactory.port", "465");
        // m_properties.put("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");
        m_properties.put("mail.smtps.auth", "true");
        //  m_properties.put("mail.smtp.port", "465");
        m_properties.put("mail.debug", "true");
        // m_properties.put("mail.smtp.ssl.enable", "true");


        m_Session = Session.getInstance(m_properties, new Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("crumbs.anastazi", "crumbs12345"); // username and the password
            }

        });

        m_simpleMessage = new MimeMessage(m_Session);
        m_toAddress = new InternetAddress(client.getMail());

        m_fromAddress = new InternetAddress("crumbs.anastazi@gmail.com");
        m_simpleMessage.setFrom(m_fromAddress);
        m_simpleMessage.setRecipient(MimeMessage.RecipientType.TO, m_toAddress);
        if (request.getCrumbsRequestsState().getId() == 2) {//if from new to in progress
            m_simpleMessage.setSubject("Your request was registered (ID :" + request.getId() + " )");
            m_simpleMessage.setContent("Your request is being processed. Our manager will assign it to engineer and send mail to you. ", "text/plain");
        } else if (request.getCrumbsRequestsState().getId() == 3) {     //if in progress to assessed

            CrumbsDateAndTimeDAO dao = SpringBeansFactory.getInstance().getBeanByClass(CrumbsDateAndTimeDAO.class);
            try {
                List<CrumbsDateAndTime> dates = dao.getByRequestId(request.getId());
                CrumbsDateAndTime time = dates.get(0);
                m_simpleMessage.setSubject("Your request was assessed (ID :" + request.getId() + " )");
                String DATE_FORMAT = "dd/MM/yyyy HH:mm";
                SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
                m_simpleMessage.setContent("Your request was assessed. Time:  " + sdf.format(time.getAssignedTimeBegin()) + " - " + sdf.format(time.getAssignedTimeEnd()), "text/plain");
            } catch (SQLException e) {
                e.printStackTrace();
            }


        }


        Transport transport = m_Session.getTransport("smtps");
        try {
            transport.connect("smtp.gmail.com", 465, "crumbs.anastazi", "crumbs12345");
            transport.sendMessage(m_simpleMessage, m_simpleMessage.getAllRecipients());
        } finally {
            transport.close();
        }
        //Transport.send(m_simpleMessage);

        return true;
    }

    @Override
    public CrumbsRequest initializeAdditioools(int idOfRequest) throws Exception {
        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsRequestDAO requestDAO = (CrumbsRequestDAO) factory.getCrumbsRequestDAO();
        CrumbsRequest req = null;
        try {
            req = requestDAO.initByAdditionalTools(idOfRequest);
        } catch (SQLException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return req;
        //requestDAO
    }

    @Override                             //TODO mamager (rofl)
    public CrumbsRequest lastCommentFromMamager(int requestID) throws SQLException {
        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsRequest request = null;
        CrumbsUserDAO managerDAO = (CrumbsUserDAO) factory.getCrumbsUserDAO();
        CrumbsProcessHistoryDAO historyDAO = (CrumbsProcessHistoryDAO) factory.getCrumbsProcessHistoryDAO();
        try {
            CrumbsUser manager = (CrumbsUser) managerDAO.getByPositionId(2);
            historyDAO.getHistoryForUser(requestID, manager.getUserId());
            CrumbsRequestDAO reqDAO = (CrumbsRequestDAO) factory.getCrumbsRequestDAO();
            request = reqDAO.getById(requestID);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return request;
    }

    @Override
    public Boolean sendForProcessing(int idSender, int idOfRequest) throws SQLException {
        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsUser sender = (CrumbsUser) factory.getCrumbsUserDAO().getById(idSender);
        CrumbsRequest request = (CrumbsRequest) factory.getCrumbsRequestDAO().getById(idOfRequest);

        //Todo find Client by request's id
        CrumbsRequestDAO dao = (CrumbsRequestDAO) factory.getCrumbsRequestDAO();
        CrumbsClient client = request.getCrumbsClient();
        this.sendToManager(factory, request, sender);

        if (request.getCrumbsRequestsState().getId() == 1) {

            try {
                CrumbsRequestsStateDAO stateDAO = (CrumbsRequestsStateDAO) factory.getCrumbsRequestsStateDAO();
                request.setCrumbsRequestsState(stateDAO.getById(2));
                ((CrumbsRequestDAO) factory.getCrumbsRequestDAO()).update(request);
            } catch (SQLException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        } else {
            try {
                CrumbsRequestsStateDAO stateDAO = (CrumbsRequestsStateDAO) factory.getCrumbsRequestsStateDAO();
                request.setCrumbsRequestsState(stateDAO.getById(3));
                ((CrumbsRequestDAO) factory.getCrumbsRequestDAO()).update(request);
            } catch (SQLException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        }
        //dao.findClientIdByRequest(operator.getUserId());

        //   (CrumbsClient) factory.getCrumbsClientDAO().getById(clientID);
        try {
            this.sendClientReport(client, request);
            return true;
        } catch (MessagingException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }


        return true;
    }

    private boolean sendToManager(DAOFactory factory, CrumbsRequest request, CrumbsUser sender) {


        CrumbsUserDAO userDAO = (CrumbsUserDAO) factory.getCrumbsUserDAO();


        try {
            CrumbsUser receiver;

            if (sender.getUserId() != 4) {
                receiver = (CrumbsUser) userDAO.getByPositionId(2);
            } else {
                receiver = (CrumbsUser) request.getCrumbsUsers().toArray()[0];
            }
            long timeOfSending = System.currentTimeMillis();
            java.sql.Date fixeDateofSending = new java.sql.Date(timeOfSending);

            CrumbsProcessHistory historyItemOfSending = new CrumbsProcessHistory();
            historyItemOfSending.setCrumbsUserBySenderId(sender);
            historyItemOfSending.setCrumbsUserByRecieverId(receiver);
            historyItemOfSending.setCrumbsRequest(request);
            historyItemOfSending.setFixedDate(fixeDateofSending);
            factory.getCrumbsProcessHistoryDAO().add(historyItemOfSending);


        } catch (SQLException e) {
            e.printStackTrace();
        }


        return true;
    }

    @Override
    public Boolean saveProccessHistoryItem(int idSender, int idReciever, int idRequest, String comment, String dateofCreation) {
        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsUser sender = null;
        CrumbsProcessHistory historyItemOfSending = new CrumbsProcessHistory();
        CrumbsRequest request = null;

        try {
            sender = (CrumbsUser) factory.getCrumbsUserDAO().getById(idSender);
            request = (CrumbsRequest) factory.getCrumbsRequestDAO().getById(idRequest);

            historyItemOfSending.setCrumbsUserBySenderId(sender);
            historyItemOfSending.setCrumbsUserByRecieverId(sender);
            historyItemOfSending.setCrumbsRequest(request);
            historyItemOfSending.setFixedDateConverter(dateofCreation);
            historyItemOfSending.setCommentText(comment);
            factory.getCrumbsProcessHistoryDAO().add(historyItemOfSending);
            //        java.util.logging.Logger.getLogger(comment).log(Level.INFO, comment);
            //      java.util.logging.Logger.getLogger(historyItemOfSending.getCommentText()).log(Level.INFO, "" + historyItemOfSending.getId());
            //   System.console().printf("!!!!!!!!!!!!!!"+historyItemOfSending.getCommentText()+ " " + historyItemOfSending.getCrumbsRequest().getId());
            return true;

        } catch (SQLException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }


        return false;
    }

    @Override
    public Boolean closeRequest(CrumbsRequest updateRequest, Map<CrumbsCatalogOfTools, Integer> actualToolsAndAmount) {
        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        for (CrumbsCatalogOfTools tool : actualToolsAndAmount.keySet()) {
            CrumbsAdditionalTools at = new CrumbsAdditionalTools();
            at.setCrumbsRequest(updateRequest);

            at.setCrumbsCatalogOfTools(tool);
            at.setAmount(actualToolsAndAmount.get(tool));
            try {
                factory.getCrumbsAdditionalToolsDAO().add(at);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        return true;
    }

    public void importRequest() throws Exception {
        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        try {


            File file = new File("D:\\request.xml");
            JAXBContext jaxbContext = JAXBContext.newInstance(CrumbsRequest.class);

            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            CrumbsRequest crumbsRequest = (CrumbsRequest) jaxbUnmarshaller.unmarshal(file);


            //System.out.println("ID Request --> " + crumbsRequest.getId());
            //System.out.println("ID Client --> " + crumbsRequest.getCrumbsClient().getId());
            //System.out.println(crumbsRequest.getCrumbsClient().getName());
            //System.out.println(crumbsRequest.getCrumbsClient().getAdress());
            CrumbsRequestsState state = factory.getCrumbsRequestsStateDAO().getById(2);
            crumbsRequest.setCrumbsRequestsState(state);
            //System.out.println(crumbsRequest.getCrumbsRequestsState().getId());//
            //System.out.println(crumbsRequest.getRequestInfo());
            //System.out.println(crumbsRequest.getActualTimeOfWork());
            //System.out.println(crumbsRequest.getCrumbsClient().getMail());
            //System.out.println(crumbsRequest.getDateOfCreation());
            // (CrumbsDateAndTime crumbsDateAndTime2 : crumbsRequest.getCrumbsDateAndTimes())
            //System.out.print("DATE --> " + crumbsDateAndTime2.getDateBegin() + "  " + crumbsDateAndTime2.getDateEnd());
            //for (CrumbsRequestAndWork crumbsRequestAndWork2 : crumbsRequest.getCrumbsRequestAndWorks())
            //System.out.print("Amount ---> " + crumbsRequestAndWork2.getAmountOfWork());


            factory.getCrumbsClientDAO().add(crumbsRequest.getCrumbsClient());

            for (CrumbsDateAndTime crumbsDateAndTime : crumbsRequest.getCrumbsDateAndTimes())
                crumbsDateAndTime.setCrumbsRequest(crumbsRequest);


            for (CrumbsRequestAndWork crumbsRequestAndWork : crumbsRequest.getCrumbsRequestAndWorks()) {
                crumbsRequestAndWork.setCrumbsRequest(crumbsRequest);
                crumbsRequestAndWork.setAmountOfWork(crumbsRequestAndWork.getAmountOfWork());
                crumbsRequestAndWork.setCrumbsCatalogOfWork(crumbsRequestAndWork.getCrumbsCatalogOfWork());
            }

            factory.getCrumbsRequestDAO().add(crumbsRequest);

            for (CrumbsRequestAndWork crumbsRequestAndWork : crumbsRequest.getCrumbsRequestAndWorks()) {
                factory.getCrumbsRequestAndWorkDAO().add(crumbsRequestAndWork);
            }

        } catch (JAXBException e) {
            e.printStackTrace();
        }


    }


    @Override
    public Boolean deleteRequests(List<Integer> requests_id) throws SQLException {
        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsRequestDAO crumbsRequestDAO = (CrumbsRequestDAO) factory.getCrumbsRequestDAO();
        List<CrumbsRequest> crumbsRequestList = new ArrayList<CrumbsRequest>();
        try {
            for (int id : requests_id)
                crumbsRequestList.add(crumbsRequestDAO.getById(id));
            crumbsRequestDAO.deleteAll(crumbsRequestList);
        } catch (SQLException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

        return true;
    }


}